#pragma once

#include <atomic>
#include <iostream>
#include <map>
#include <mutex>

#include "NuRaft.h"
#include "log_store.hxx"

namespace keeper_server {


class KeeperLogStore : public nuraft::log_store {
 public:
  KeeperLogStore();

  ~KeeperLogStore();

  __nocopy__(KeeperLogStore);

  ulong next_slot() const;

  ulong start_index() const;

  NuRaftLogEntryPtr last_entry() const;

  ulong append(NuRaftLogEntryPtr& entry);

  void write_at(ulong index, NuRaftLogEntryPtr& entry);

  nuraft::ptr<NuRaftLogEntries> log_entries(ulong start, ulong end);

  nuraft::ptr<NuRaftLogEntries> log_entries_ext(
      ulong start, ulong end, nuraft::int64 batch_size_hint_in_bytes = 0);

  NuRaftLogEntryPtr entry_at(ulong index);

  ulong term_at(ulong index);

  NuRaftBufferPtr pack(ulong index, nuraft::int32 cnt);

  void apply_pack(ulong index, NuRaftBuffer& pack);

  bool compact(ulong last_log_index);

  bool flush() { return true; }

  void close();

 private:
  static NuRaftLogEntryPtr make_clone(const NuRaftLogEntryPtr& entry);

  std::map<ulong, NuRaftLogEntryPtr> logs_;
  mutable std::mutex logs_lock_;
  std::atomic<ulong> start_idx_;
};

}  // namespace keeper_server
